package com.job.admin.job.schedule;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.Trigger.TriggerState;
import org.quartz.impl.matchers.GroupMatcher;
import org.quartz.impl.triggers.CronTriggerImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.Assert;

import com.job.admin.job.dao.JobDao;
import com.job.admin.job.jobbean.RemoteHttpJobBean;
import com.job.admin.job.model.JobInfoModel;
import com.job.admin.job.thread.JobFailMonitorHelper;
import com.job.admin.job.thread.JobRegistryMonitorHelper;
import com.job.admin.jobGroup.dao.JobGroupDao;
import com.job.admin.jobregister.dao.JobRegisterDao;
import com.job.admin.log.dao.LogDao;
import com.job.core.rpc.NetComServerFactory;
/**
 * 
 * @Title: JobDynamicScheduler.java
 * @Package: com.job.admin.job.schedule
 * @Description: job执行中心
 * @author: sunwei
 * @date: 2017年6月19日 下午1:22:58
 * @version: V1.0
 */
public final class JobDynamicScheduler implements ApplicationContextAware,InitializingBean {
    private static Logger logger=LoggerFactory.getLogger(JobDynamicScheduler.class);
    private static Scheduler scheduler;
    public static LogDao logDao;
    public static JobDao jobDao;
    public static JobRegisterDao jobRegisterDao;
    public static JobGroupDao jobGroupDao;
    
    public static Scheduler getScheduler() {
        return scheduler;
    }

    public static void setScheduler(Scheduler scheduler) {
        JobDynamicScheduler.scheduler = scheduler;
    }
    // init
    private NetComServerFactory serverFactory = new NetComServerFactory();
    public void init(){
//	ExecuRegistThread.getExecuRegistThread().start();
	// admin registry monitor run
       JobRegistryMonitorHelper.getInstance().start();
        // admin monitor run
        JobFailMonitorHelper.getInstance().start();	
	
    }
 // destroy
    public void destroy(){
        // admin registry stop
        JobRegistryMonitorHelper.getInstance().toStop();

        // admin monitor stop
        JobFailMonitorHelper.getInstance().toStop();
        serverFactory.destroy();
    }
    
    @Override
    public void afterPropertiesSet() throws Exception {
	 Assert.notNull(scheduler, "quartz scheduler is null");
	 logger.info(">>>>>>>>> init quartz scheduler success.[{}]", scheduler);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext)
	    throws BeansException {
	JobDynamicScheduler.logDao = applicationContext.getBean(LogDao.class);
	JobDynamicScheduler.jobDao = applicationContext.getBean(JobDao.class);
	JobDynamicScheduler.jobRegisterDao = applicationContext.getBean(JobRegisterDao.class);
	JobDynamicScheduler.jobGroupDao = applicationContext.getBean(JobGroupDao.class);

    }
    /**
     * 
     * @Title: getJobList
     * @Description:此方法可能会被废弃 @Deprecated
     * @author:sunwei
     * @createTime:2017年8月6日下午9:35:51
     * @return
     */
    @Deprecated
    public static List<Map<String, Object>> getJobList(){
 	List<Map<String, Object>> jobList = new ArrayList<Map<String,Object>>();
 	try {
 	    if (scheduler.getJobGroupNames()==null || scheduler.getJobGroupNames().size()==0) {
 		return null;
 	    }
 	    String groupName = scheduler.getJobGroupNames().get(0);
 	    Set<JobKey> jobKeys = scheduler.getJobKeys(GroupMatcher.jobGroupEquals(groupName));
 	    if (jobKeys!=null && jobKeys.size()>0) {
 		for (JobKey jobKey : jobKeys) {
 		    TriggerKey triggerKey = TriggerKey.triggerKey(jobKey.getName(), Scheduler.DEFAULT_GROUP);
 		    Trigger trigger = scheduler.getTrigger(triggerKey);
 		    JobDetail jobDetail = scheduler.getJobDetail(jobKey);
 		    TriggerState triggerState = scheduler.getTriggerState(triggerKey);
 		    Map<String, Object> jobMap = new HashMap<String, Object>();
 		    jobMap.put("TriggerKey", triggerKey);
 		    jobMap.put("Trigger", trigger);
 		    jobMap.put("JobDetail", jobDetail);
 		    jobMap.put("TriggerState", triggerState);
 		    jobList.add(jobMap);
 		}
 	    }
 			
 	} catch (SchedulerException e) {
 	    e.printStackTrace();
 	    return null;
 	}
 	return jobList;
    }

    // fill job info
    /**
     * 
     * @Title: fillJobInfo
     * @Description: 填充job 信息 corn表达式等
     * @author:sunwei
     * @createTime:2017年8月6日下午9:41:27
     * @param jobInfo
     */
    public static void fillJobInfo(JobInfoModel jobInfo) {
	// TriggerKey : name + group
	String group = String.valueOf(jobInfo.getJobGroup());
	String name = String.valueOf(jobInfo.getId());
	TriggerKey triggerKey = TriggerKey.triggerKey(name, group);
	try {
	    Trigger trigger = scheduler.getTrigger(triggerKey);
	    TriggerState triggerState = scheduler.getTriggerState(triggerKey);
	    // parse params
	    if (trigger != null && trigger instanceof CronTriggerImpl) {
		String cronExpression = ((CronTriggerImpl) trigger)
			.getCronExpression();
		jobInfo.setJobCron(cronExpression);
	    }
	    // JobKey jobKey = new JobKey(jobInfo.getJobName(),
	    // String.valueOf(jobInfo.getJobGroup()));
	    // JobDetail jobDetail = scheduler.getJobDetail(jobKey);
	    // String jobClass = jobDetail.getJobClass().getName();
	    if (triggerState != null) {
		jobInfo.setJobStatus(triggerState.name());
	    }
	} catch (SchedulerException e) {
	    e.printStackTrace();
	}
    }
    /**
     * 
     * @Title: addJob
     * @Description:新增执行job
     * @author:sunwei
     * @createTime:2017年8月6日下午9:42:18
     * @param jobName 任务名称
     * @param jobGroup 任务组
     * @param cronExpression 执行时间
     * @return
     * @throws SchedulerException
     */
    public static boolean addJob(String jobName, String jobGroup,String cronExpression) throws SchedulerException {
	// TriggerKey : name + group
	TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
	JobKey jobKey = new JobKey(jobName, jobGroup);
	// TriggerKey valid if_exists
	if (checkExists(jobName, jobGroup)) {
	    logger.info(">>>>>>>>> addJob fail, job already exist, jobGroup:{}, jobName:{}", jobGroup, jobName);
	    return false;
	}

	// CronTrigger : TriggerKey + cronExpression //
	// withMisfireHandlingInstructionDoNothing 忽略掉调度终止过程中忽略的调度
	CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression).withMisfireHandlingInstructionDoNothing();
	CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withSchedule(cronScheduleBuilder).build();
	// JobDetail : jobClass
	Class<? extends Job> jobClass_ = RemoteHttpJobBean.class; // Class.forName(jobInfo.getJobClass());

	JobDetail jobDetail = JobBuilder.newJob(jobClass_).withIdentity(jobKey)
		.build();
	/*
	 * if (jobInfo.getJobData()!=null) { JobDataMap jobDataMap =
	 * jobDetail.getJobDataMap();
	 * jobDataMap.putAll(JacksonUtil.readValue(jobInfo.getJobData(),
	 * Map.class)); // JobExecutionContext
	 * context.getMergedJobDataMap().get("mailGuid"); }
	 */

	// schedule : jobDetail + cronTrigger
	Date date = scheduler.scheduleJob(jobDetail, cronTrigger);

	logger.info(
		">>>>>>>>>>> addJob success, jobDetail:{}, cronTrigger:{}, date:{}",
		jobDetail, cronTrigger, date);
	return true;
    }
    /**
     * 
     * @Title: triggerJob
     * @Description:执行job
     * @author:sunwei
     * @createTime:2017年8月2日下午3:47:33
     * @param jobName
     * @param jobGroup
     * @return
     * @throws SchedulerException
     */
    public static boolean triggerJob(String jobName, String jobGroup) throws SchedulerException {
    	// TriggerKey : name + group
    	JobKey jobKey = new JobKey(jobName, jobGroup);
        boolean result = false;
        if (checkExists(jobName, jobGroup)) {
            scheduler.triggerJob(jobKey);
            result = true;
            logger.info(">>>>>>>>>>> runJob success, jobKey:{}", jobKey);
        } else {
        	logger.info(">>>>>>>>>>> runJob fail, jobKey:{}", jobKey);
        }
        return result;
    }
    
    /**
     * 
     * @Title: checkExists
     * @Description:检查任务是否存在
     * @author:sunwei
     * @createTime:2017年8月2日下午3:53:14
     * @param jobName
     * @param jobGroup
     * @return
     * @throws SchedulerException
     */
    public static boolean checkExists(String jobName, String jobGroup)throws SchedulerException {
	TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
	return scheduler.checkExists(triggerKey);
    }

}
